﻿using System;
using System.Linq;
using System.Linq.Expressions;
using WindowsPhoneMvp.Navigation;
using WindowsPhoneMvp.Phone;

namespace WindowsPhoneMvp
{
    ///<summary>
    /// Represents a presenter in a Windows Phone Model-View-Presenter application.
    ///</summary>
    ///<typeparam name="TView">The type of view.</typeparam>
    ///<typeparam name="TModel">The type of model (assigned to DataContext).</typeparam>
    public abstract class Presenter<TView, TModel> : Presenter<TView>, IPresenter<TView, TModel>
        where TView : class, IView
        where TModel : class, new()
    {

        /// <summary>
        /// Constructs a new Presenter.
        /// Because the NavigationService was not passed in, it will be available on View.Load.
        /// </summary>
        /// <param name="view">The view instance.</param>
        protected Presenter(TView view)
            : base(view)
        {
            InitializeDefaultModel(view);
        }

        protected Presenter(TView view, INavigationService navigationService)
            : base(view, navigationService)
        {
            InitializeDefaultModel(view);
        }

        /// <summary>
        /// Specifies the property on the bound model to be transiently persisted (on activated and deactivated events)
        /// </summary>
        /// <param name="property">Path to property, eg. x => x.MyProperty</param>
        protected void Transient(Expression<Func<TModel, object>> property)
        {
            new TransientBuilder<TModel>(this, () => Model).Property(property);
        }

        static void InitializeDefaultModel(TView view)
        {
            var viewType = view.GetType();
            if(viewType.GetCustomAttributes(typeof(InheritModelAttribute), true).Any())
                return;

            var defaultModel = Activator.CreateInstance(typeof(TModel));
            view.DataContext = defaultModel;
        }

        /// <summary>The Model that is bound to the View</summary>
        /// <remarks>
        /// Provides access to the Model without needing a generic MvpPhoneApplication page
        /// and without needing to go through the view
        /// </remarks>
        public TModel Model
        {
            get { return (TModel)View.DataContext; }
        }
    }
}
